﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Runtime.InteropServices;
namespace eTerm.NetSocket
{
    public abstract class BaseTermSocket:__TSession
    {
        #region 变量定义
        private byte[] buffer=new byte[BUFFERSIZE];
        private const int BUFFERSIZE = 64 * 1024;
        private const int KEEPALIVESIZE = 12;
        //private long m_PakcketId = 0;
        private long m_SentCount = 0;
        private long m_ReceiveCount = 0;
        private const int DEFAULT_TIMEOUT = 20 * 1000;
        private string m_IntervalCmd = @"IG";
        Timer socketWatcher = null;
        #endregion

        #region 单实例应用
        private static BaseTermSocket _singlestone = null;
        #endregion

        #region 构造函数
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseTermSocket"/> class.
        /// </summary>
        /// <param name="address">The address.</param>
        /// <param name="port">The port.</param>
        /// <param name="isSsl">if set to <c>true</c> [is SSL].</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="rid">The rid.</param>
        /// <param name="sid">The sid.</param>
        /// <param name="localPoint">The local point.</param>
        protected BaseTermSocket(string address, int port, bool isSsl, string userName, string password, byte rid, byte sid, string localPoint)
        {
            Address = address;
            Port = port;
            IsSsl = isSsl;
            UserName = userName;
            Password = password;
            RID = rid;
            SID = sid;
            LocalPoint = localPoint;
            Groups = new List<long>();
            AllowReconnect = true;
        }
        #endregion

        #region 属性定义
        /// <summary>
        /// 单实例应用
        /// </summary>
        public static BaseTermSocket SingleStone {
            get {
                return _singlestone;
            }
        }

        /// <summary>
        /// Gets or sets the RID.
        /// </summary>
        /// <value>The RID.</value>
        public byte RID { get;private set; }

        /// <summary>
        /// Gets or sets the SID.
        /// </summary>
        /// <value>The SID.</value>
        public byte SID { get; private set; }

        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        /// <value>The name of the user.</value>
        public string UserName { get; private set; }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>The password.</value>
        public string Password { get; private set; }

        /// <summary>
        /// Gets or sets the local point.
        /// </summary>
        /// <value>The local point.</value>
        public string LocalPoint { get; private set; }

        /// <summary>
        /// 配置被分配的时间
        /// </summary>
        internal DateTime? AssignDateTime { get; set; }


        /// <summary>
        /// Gets or sets the groups.
        /// </summary>
        /// <value>The groups.</value>
        public List<long> Groups { get; set; }

        /// <summary>
        /// 该连接是否允许执行断开后的动作
        /// </summary>
        public bool AllowReconnect { private get; set; }

        /// <summary>
        /// Gets or sets the code.
        /// </summary>
        /// <value>The code.</value>
        public long Code { get; set; }


        /// <summary>
        /// Gets or sets the server point.
        /// </summary>
        /// <value>The server point.</value>
        protected IPEndPoint EndPoint { get; private set; }

        /// <summary>
        /// 发送帧数.
        /// </summary>
        /// <value>The sent count.</value>
        public long SentCount { get { return m_SentCount; } set { m_SentCount = value; } }

        /// <summary>
        /// 接收帧数.
        /// </summary>
        /// <value>The receive count.</value>
        public long ReceiveCount { get { return m_ReceiveCount; } internal set { m_ReceiveCount = value; } }

        /// <summary>
        /// Gets or sets the validate date time.
        /// </summary>
        /// <value>The validate date time.</value>
        public DateTime? ValidateDateTime { get; protected set; }

        /// <summary>
        /// 连接维护间隔（秒钟）
        /// </summary>
        public int? AutoSendInterval { get; set; }

        /// <summary>
        /// 间隙指令(默认：IG).
        /// </summary>
        /// <value>The interval command.</value>
        public string IntervalCommand { get { return m_IntervalCmd; } set { m_IntervalCmd = value; } }

        /// <summary>
        /// Gets or sets the read timeout.
        /// </summary>
        /// <value>The read timeout.</value>
        public int? ReadTimeout { get; set; }

        /// <summary>
        /// Gets or sets the write timeout.
        /// </summary>
        /// <value>The write timeout.</value>
        public int? WriteTimeout { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is validated.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is validated; otherwise, <c>false</c>.
        /// </value>
        public bool IsValidated { get;protected set; }

        /// <summary>
        /// Gets or sets the T session.
        /// </summary>
        /// <value>The T session.</value>
        public eTerm363Session TSession { get; set; }

        public bool IsOpen { get; set; }

        /// <summary>
        /// Gets or sets the si text.
        /// </summary>
        /// <value>The si text.</value>
        public string SiText { get; set; }

        public int SessionTimeInterval
        {
            get
            {
                TimeSpan ts = DateTime.Now.Subtract(LastPacket??DateTime.Now);
                return Math.Abs((int)ts.TotalSeconds);
            }
        }
        #endregion

        #region 事件定义
        /// <summary>
        /// 连接成功.
        /// </summary>
        public event EventHandler<SocketAsyncEventArgs> OnConnected;


        /// <summary>
        /// 配置超时无响应
        /// </summary>
        public event EventHandler OnSocketTimeout;

        /// <summary>
        /// 配置自动IG维护事件
        /// </summary>
        public event EventHandler OnAutoCommand;




        /// <summary>
        /// Occurs when [on receive exception].
        /// </summary>
        public event EventHandler<TSessionExceptionEventArgs> OnReceiveException;


        /// <summary>
        /// Occurs when [on read packet].
        /// </summary>
        public event EventHandler<SocketPacketEventArgs> OnReadPacket;

        /// <summary>
        /// 配置被踢出.
        /// </summary>
        public event EventHandler OnKickedOff;


        /// <summary>
        /// 发送指令包事件 
        /// </summary>
        public event EventHandler<SocketPacketEventArgs> OnWritePacket;

        /// <summary>
        /// Occurs when [on disconnect].
        /// </summary>
        public event EventHandler OnDisconnecting;

        /// <summary>
        /// Occurs when [on disconnected].
        /// </summary>
        public event EventHandler OnDisconnected;

        /// <summary>
        /// Occurs when [on SSL authenticated].
        /// </summary>
        public event EventHandler<SslSocketCertificateValidationEventArgs> OnSslAuthenticated;

        /// <summary>
        /// Occurs when [on validated].
        /// </summary>
        public event EventHandler OnValidated;

        /// <summary>
        /// 指令分析
        /// </summary>
        /// <param name="packetID"></param>
        /// <param name="buffer"></param>
        /// <param name="TSession"></param>
        /// <returns></returns>
        public delegate void AnalysisPacketVoid(SocketPacketEventArgs Args);

        public AnalysisPacketVoid AnalysisPacket { get; set; }
        #endregion

        #region 心跳包
        /// <summary>
        /// Keeps the alive.
        /// </summary>
        /// <param name="onOff">The on off.</param>
        /// <param name="keepAliveTime">The keep alive time.</param>
        /// <param name="keepAliveInterval">The keep alive interval.</param>
        /// <returns></returns>
        private byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
        {
            byte[] buffer = new byte[KEEPALIVESIZE];
            BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
            BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
            BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
            return buffer;
        }
        #endregion

        #region Connect
        ///// <summary>
        ///// 使用默认授权认证
        ///// </summary>
        //public virtual void Connect() {
        //    this.Connect(KeyManager);
        //}

        /// <summary>
        /// Connects this instance.
        /// </summary>
        public virtual void Connect() {

            //if (manager == null)
            //    throw new ArgumentException(@"未初始化授权管理器。");

            //if (!manager.IsValid)
            //    throw new WaitHandleCannotBeOpenedException(@"授权失败，无法使用该服务,请联系供应商.");

            foreach (IPAddress i in Dns.GetHostAddresses(Address))
            {
                try
                {
                    SyncSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    ReceiveCount = 0;
                    SentCount = 0;
                    SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
                    EndPoint = new IPEndPoint(i, Port);
                    connectArgs.UserToken = SyncSocket;
                    connectArgs.RemoteEndPoint = EndPoint;
                    connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
                    if (!string.IsNullOrEmpty(LocalPoint))
                    {
                        LocalEP = new IPEndPoint(IPAddress.Parse(LocalPoint), 0);
                        SyncSocket.Bind(LocalEP);
                    }
                    ReconnectCount++;
                    SessionId = SyncSocket.Handle.ToInt32();
                    SyncSocket.ConnectAsync(connectArgs);
                    break;
                }
                catch { }
            }
        }


        /// <summary>
        /// Called when [connect].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Net.Sockets.SocketAsyncEventArgs"/> instance containing the event data.</param>
        private void OnConnect(object sender, SocketAsyncEventArgs e) {
            if (OnConnected != null)
                OnConnected(this, e);
            if (!(sender as Socket).Connected) { Close(); return; }
            if (IsSsl)
                SyncNetworkStream = GetSslStream();
            else
                SyncNetworkStream = new NetworkStream(SyncSocket, true);
            SyncNetworkStream.WriteTimeout = WriteTimeout ?? DEFAULT_TIMEOUT;
            SyncNetworkStream.ReadTimeout = ReadTimeout ?? DEFAULT_TIMEOUT;
            (sender as Socket).IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 30000, 5000), null);
            LogIn();
            ReceiveDatagram();
        }

        /// <summary>
        /// 切换为SSL安全连接.
        /// </summary>
        /// <returns>是否成功切换</returns>
        protected virtual Stream GetSslStream()
        {
            SslStream _sslStream = new SslStream(new NetworkStream(SyncSocket, true), true, RemoteCertificateValidationCallback);
            try
            {
                _sslStream.AuthenticateAsClient("eTerm.NetSocket3.5");
                if (_sslStream.IsAuthenticated)
                {
                    SyncNetworkStream = _sslStream;
                    if (OnSslAuthenticated != null)
                        OnSslAuthenticated(this, new SslSocketCertificateValidationEventArgs() { Stream = _sslStream });

                }
            }
            catch (Exception ex)
            {
            }
            return _sslStream;
        }

        /// <summary>
        /// 认证代理.
        /// </summary>
        /// <value>The M_P certificate callback.</value>
        protected virtual RemoteCertificateValidationCallback m_pCertificateCallback { set; private get; }

        /// <summary>
        /// Remotes the certificate validation callback.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="certificate">The certificate.</param>
        /// <param name="chain">The chain.</param>
        /// <param name="sslPolicyErrors">The SSL policy errors.</param>
        /// <returns></returns>
        private bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            // User will handle it.
            if (m_pCertificateCallback != null)
            {
                return m_pCertificateCallback(sender, certificate, chain, sslPolicyErrors);
            }
            else
            {
                if (sslPolicyErrors == SslPolicyErrors.None || ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) > 0))
                {
                    return true;
                }

                return false;
            }
        }
        #endregion

        #region Login
        /// <summary>
        /// Logs the in.
        /// </summary>
        protected virtual void LogIn() {
            byte[] formatIp = Encoding.Default.GetBytes(string.Format(@"080027c55703{0}  3730410.000000", (SyncSocket.LocalEndPoint as IPEndPoint).Address.ToString()));
            byte[] buffer = __eTermPakcet.LogInPacket;
            Buffer.BlockCopy(Encoding.Default.GetBytes(UserName.PadRight(16, '\0').ToCharArray()), 0x00, buffer, 0x02, 16);
            Buffer.BlockCopy(Encoding.Default.GetBytes(Password.PadRight(16, '\0').ToCharArray()), 0x00, buffer, 18, 16);
            int lenghtCount = 0;
            while (lenghtCount < formatIp.Length)
            {
                buffer[0x32 + lenghtCount] = formatIp[lenghtCount++];
            }
            SendStream(buffer);
        }
        #endregion

        #region 装包重写（改装协议包）
        /// <summary>
        /// 数据包编码.
        /// </summary>
        /// <param name="dataPakcet">原始数据包.</param>
        /// <returns></returns>
        public virtual byte[] Enpacket(byte[] dataPakcet)
        {
            byte[] bytes1;
            List<byte> Command = new List<byte>();
            bytes1 = new byte[2];
            bytes1[0] = 1;
            Command.AddRange(bytes1);
            bytes1 = BitConverter.GetBytes((ushort)((0x13 + dataPakcet.Length) + 2));
            Array.Reverse(bytes1);
            Command.AddRange(bytes1);
            Command.AddRange(new byte[] { 0, 0, 0, 0x01, RID, SID, 0x70, 0x02, 0x1b, 0x0B, 0x21, 0x20, 0, 0x0f, 0x1e });

            Command.AddRange(dataPakcet);
            Command.AddRange(new byte[] { 0x20, 3 });


            return Command.ToArray();
        }
        #endregion

        #region SendStream
        /// <summary>
        /// 发送符串数据包.
        /// </summary>
        /// <param name="dataPacket">The data packet.</param>
        public virtual void SendStream(string dataPacket)
        {
            SendStream(Enpacket(__eTermPakcet.getTranslateToeTermChinese(dataPacket)));
        }

        /// <summary>
        /// Sends the stream.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <summary>
        /// 发送字节流.
        /// </summary>
        /// <param name="Packet">The packet.</param>
        public void SendStream(byte[] Packet)
        {
            try
            {
                if (SurplusCmdCount <= 0) {
                    AllowReconnect = false;
                    OnSessionReceiveException(new NotSupportedException(string.Format(@"配置 {0} 流量超额被怎么断线",UserName)));
                    Close();
                    return;
                }
                if ( SyncNetworkStream.CanWrite)
                {
                    //异步读取文件,把FileStream对象作为异步的参数// <-
                    AsyncCallback callback = new AsyncCallback(OnWriteCompletion);
                    IAsyncResult async = SyncNetworkStream.BeginWrite(Packet, 0, Packet.Length, callback, SyncNetworkStream); // <-
                    Outpacket = new SocketPacket();
                    Outpacket.Put(Packet,0,Packet.Length);
                }
            }
            catch (IOException ex)
            {
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// Called when [write completion].
        /// </summary>
        /// <param name="asyncResult">The async result.</param>
        void OnWriteCompletion(IAsyncResult asyncResult)
        {
            try
            {
                Stream fs = asyncResult.AsyncState as Stream;
                fs.EndWrite(asyncResult);
                asyncResult.AsyncWaitHandle.Close();
                SurplusCmdCount--;
                Interlocked.Increment(ref m_SentCount);
                if (OnWritePacket != null)
                    OnWritePacket(this, new SocketPacketEventArgs() { });
            }
            catch { }
        }
        #endregion

        #region 接收数据
        /// <summary>
        /// Receives the datagram.
        /// </summary>
        public void ReceiveDatagram()
        {
            lock (this)
            {

                try  // 一个客户端连续做连接 或连接后立即断开，容易在该处产生错误，系统不认为是错误
                {
                    // 开始接受来自该客户端的数据
                    SyncNetworkStream.BeginRead(buffer, 0, buffer.Length, this.EndReceiveDatagram, SyncNetworkStream);

                }
                catch (Exception err)  // 读 Socket 异常，准备关闭该会话
                {
                    //m_disconnectType = TDisconnectType.Exception;
                    //m_state = TSessionState.Inactive;

                    //this.OnSessionReceiveException(err);
                }
            }
        }


        /// <summary>
        /// Validates the packet.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        protected virtual bool ValidatePacket(byte[] buffer, int length) {
            if (!IsValidated) return true;
            if (buffer.Length>8 && buffer[8] == RID && buffer[9] == SID){
                return buffer[length - 1] == 0x03;
            }
            else if (buffer.Length == 5) {
                return true;
            }
            else
            {
                return true;
            }
            //return buffer.Length == 0 || (IsValidated && (buffer[1] == 0xF8 || buffer[length - 1] == 0x03));
        }


        private void EndReceiveDatagram(IAsyncResult iar)
        {
            lock (this)
            {
                try {
                    if (SyncNetworkStream == null) return;
                    // Shutdown 时将调用 ReceiveData，此时也可能收到 0 长数据包
                    int readBytesLength = SyncNetworkStream.EndRead(iar);
                    LastPacket = DateTime.Now;
                    if (readBytesLength == 0) {
                        //m_disconnectType = TDisconnectType.Normal;
                        //m_state = TSessionState.Inactive;
                        Close();
                        return;
                    }
                    else if (readBytesLength == 5 && (
                            buffer[0] == 0x01
                            &&
                        buffer[1] == 0xfc
                        &&
                        buffer[2] == 0x00
                        &&
                        buffer[3] == 0x05
                        &&
                        buffer[4] == 0x39
                        )) {            //配置被踢出
                        FireOnKickedOff();
                        return;
                    }
                    else  // 正常数据包
                    {
                        // 合并报文，按报文头、尾字符标志抽取报文，将包交给数据处理器
                        Inpacket.Put(buffer, 0, readBytesLength);
                        if ( /*readBytesLength<BUFFERSIZE &&*/(ValidatePacket(Inpacket.GetStream(), Inpacket.GetStream().Length))) {
                            Interlocked.Increment(ref m_ReceiveCount);
                            FireOnReadPacket(Inpacket);
                            Inpacket = new SocketPacket();
                        }
                    }
                }
                catch (IOException err) {
                    if (err.InnerException is SocketException) {
                        if ((err.InnerException as SocketException).ErrorCode == 10053
                            ||
                            (err.InnerException as SocketException).ErrorCode == 10054
                            )
                            Close();
                        return;
                    }
                }
                catch (Exception err)  // 读 socket 异常，关闭该会话，系统不认为是错误（这种错误可能太多）
                {
                    //if (m_state == TSessionState.Active)
                    //{
                    //    m_disconnectType = TDisconnectType.Exception;
                    //    m_state = TSessionState.Inactive;
                    OnSessionReceiveException(err);
                    //    this.OnSessionReceiveException(err);
                    //}
                }
                //继续接收来自来客户端的数据 
                ReceiveDatagram();
            }
        }


        #endregion

        #region 事件触发器
        /// <summary>
        /// 触发数据读取事件 .
        /// </summary>
        /// <param name="packet">The packet.</param>
        protected virtual void FireOnReadPacket(SocketPacket packet) {
           //Interlocked.Increment(ref m_PakcketId);
            SocketPacketEventArgs connArgs = new SocketPacketEventArgs();
            byte[] data = Inpacket.GetStream();

            connArgs.PacketId = m_ReceiveCount;
            connArgs.SetBuffer(data, 0, data.Length);
            connArgs.AcceptSocket = SyncSocket;
            connArgs.eTermSession = this;


            connArgs.SocketError = SocketError.Success;
            if (m_ReceiveCount == 1)
            {
                SendStream(__eTermPakcet.FIRST_LOGIN);
                if (RID == 0x00)
                    RID = data[8];
                if (SID == 0x00)
                    SID = data[9];
            }
            else if (m_ReceiveCount == 2)
            {
                Thread.Sleep(500);
                SendStream(__eTermPakcet.SENCOND_LOGIN);
            }
            else if (m_ReceiveCount == 3) {
                Thread.Sleep(500);
                SendStream(__eTermPakcet.THIRD_LOGIN);
                ValidateDateTime = DateTime.Now;
                _singlestone = this;
                //KeyManager.SingleSocket = this;

                if (OnValidated != null)
                    OnValidated(this, EventArgs.Empty);



                Thread.Sleep(500);
            }
            else if (m_ReceiveCount == 4)
            {
                Thread.Sleep(500);
                IsValidated = true;
                if (!string.IsNullOrEmpty(SiText))
                    SendStream(SiText);
            }
            else
            {
                byte[] buffer = this.Outpacket.GetStream();
                string Cmd = string.Empty;
                if (buffer.Length > 8 && buffer[8] == this.RID && buffer[9] == this.SID){
                    string outStream = Encoding.Default.GetString(this.Depacket(this.Outpacket.GetStream()));

                    string inStream = Encoding.Default.GetString(this.Depacket(this.Inpacket.GetStream()));

                    connArgs.PacketName = outStream;
                    connArgs.PacketString = inStream;
                }
                if (this.AnalysisPacket != null) 
                    try{
                        this.AnalysisPacket(connArgs);
                    }
                    catch { }
                Interlocked.Increment(ref m_SentCount);
                if (OnReadPacket != null)
                    OnReadPacket(this, connArgs);
            }
        }

        /// <summary>
        /// Fires the on kicked off.
        /// </summary>
        protected virtual void FireOnKickedOff() {
            if (OnKickedOff != null)
                OnKickedOff(this, EventArgs.Empty);
            Close();
        }

        /// <summary>
        /// 触发数据断连事件.
        /// </summary>
        protected virtual void FireOnDisconnect() {
            IsValidated = false;
            ReceiveCount = 0;
            if (OnDisconnecting != null) {
                OnDisconnecting(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Called when [session receive exception].
        /// </summary>
        /// <param name="err">The err.</param>
        protected virtual void OnSessionReceiveException(Exception err)
        {
            EventHandler<TSessionExceptionEventArgs> handler = this.OnReceiveException;
            if (handler != null)
            {
                TSessionExceptionEventArgs e = new TSessionExceptionEventArgs(err, null);
                handler(this, e);
            }
        }
        #endregion

        #region 拆包重写
        /// <summary>
        /// 数据包解码.
        /// </summary>
        /// <param name="dataPacket">原始数据包.</param>
        /// <returns></returns>
        public virtual byte[] Depacket(byte[] dataPacket)
        {
            return Unpacket(dataPacket, 2);
        }

        /// <summary>
        /// 结尾字节数
        /// </summary>
        /// <param name="datapacket"></param>
        /// <param name="unlessLength"></param>
        /// <returns></returns>
        public virtual byte[] Depacket(byte[] datapacket, int unlessLength) {
            return Unpacket(datapacket, unlessLength);
        }

        /// <summary>
        /// Unpackets the specified LPS buf.
        /// </summary>
        /// <param name="lpsBuf">The LPS buf.</param>
        /// <param name="unlessLength">Length of the unless.</param>
        /// <returns></returns>
        private byte[] Unpacket(byte[] lpsBuf, int unlessLength)
        {
            //lpsBuf = lpsBuf.Select(l => (l == (byte)0x0e) ? (byte)0x20 : l).ToArray<byte>();
            List<byte> UnPacketResult = new List<byte>();
            ushort nIndex = 18;
            uint ColumnNumber = 0;
            ushort maxLength = BitConverter.ToUInt16(new byte[] { lpsBuf[3], lpsBuf[2] }, 0);
            while (nIndex++ < maxLength - unlessLength)
            {
                if (nIndex >= lpsBuf.Length) break;
                switch (lpsBuf[nIndex])
                {
                    case 0x1C:                          //红色标记
                    case 0x1D:
                        UnPacketResult.Add(0x20);
                        ColumnNumber++;
                        break;
                    case 0x62:
                    case 0x03:
                    //case 0x1E:
                    case 0x1B:
                    case 0x00:
                        break;
                    case 0x1E:
                        UnPacketResult.Add(0x0E);
                        ColumnNumber++;
                        break;
                    case 0x0D:
                        while (++ColumnNumber % 80 != 0)
                        {
                            UnPacketResult.Add(0x20);
                            continue;
                        }
                        if (ColumnNumber % 80 == 0) { UnPacketResult.Add(0x0D); ColumnNumber = 0; }
                        break;
                    case 0x0E:
                        while (true)
                        {
                            byte[] ch = new byte[] { lpsBuf[++nIndex], lpsBuf[++nIndex] };
                            if ((ch[0] == 0x1B) && (ch[1] == 0x0F))
                            {
                                break;
                            }
                            UsasToGb(ref ch[0], ref ch[1]);
                            ColumnNumber++;
                            UnPacketResult.AddRange(new byte[] { ch[0], ch[1] });
                            if (ColumnNumber % 80 == 0) { UnPacketResult.Add(0x0D); ColumnNumber = 0; }
                        }
                        break;
                    default:
                        ColumnNumber++;
                        UnPacketResult.Add(lpsBuf[nIndex]);
                        if (ColumnNumber % 80 == 0) { UnPacketResult.Add(0x0D); ColumnNumber = 0; }
                        break;
                }
            }
            return UnPacketResult.ToArray();
        }

        /// <summary>
        /// Usases to gb.
        /// </summary>
        /// <param name="c1">The c1.</param>
        /// <param name="c2">The c2.</param>
        private void UsasToGb(ref byte c1, ref byte c2)
        {
            if ((c1 > 0x24) && (c1 < 0x29))
            {
                byte tmp = c1;
                c1 = c2;
                c2 = (byte)(tmp + 10);
            }
            if (c1 > 0x24)
            {
                c1 = (byte)(c1 + 0x80);
            }
            else
            {
                c1 = (byte)(c1 + 0x8e);
            }
            c2 = (byte)(c2 + 0x80);
        }
        #endregion

        #region ToString

        private delegate void eTermCallback();
        /// <summary>
        /// 不是必要的，提供一个Close方法仅仅是为了更符合其他语言（如C++）的规范
        /// </summary>
        public override void Close()
        {
            eTermCallback m_eTerm = new eTermCallback(AsyncClose);
            m_eTerm.BeginInvoke(new AsyncCallback(delegate(IAsyncResult iar) {
                eTermCallback m = iar.AsyncState as eTermCallback;
                m.EndInvoke(iar);
                iar.AsyncWaitHandle.Close();
                if (AllowReconnect&&OnDisconnected != null)
                    OnDisconnected(this, EventArgs.Empty);
            }), m_eTerm);
        }

        private void AsyncClose() {
            FireOnDisconnect();
            base.Close();
        }
        #endregion

    }
}
